package com.ruoyi.common.utils.poi;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Excel图片提取工具类
 * 用于从Excel文件中提取图片（如二维码）并转换为Base64格式
 * 
 * @author ruoyi
 */
public class ExcelImageExtractor {
    
    private static final Logger log = LoggerFactory.getLogger(ExcelImageExtractor.class);
    
    /**
     * 图片信息实体类
     */
    public static class ImageInfo {
        /** 图片Base64编码 */
        private String base64;
        /** 图片字节数据 */
        private byte[] data;
        /** 图片格式(png/jpg等) */
        private String format;
        /** 图片所在行 */
        private int row;
        /** 图片所在列 */
        private int column;
        /** 图片宽度(像素) */
        private int width;
        /** 图片高度(像素) */
        private int height;
        
        public String getBase64() {
            return base64;
        }
        
        public void setBase64(String base64) {
            this.base64 = base64;
        }
        
        public byte[] getData() {
            return data;
        }
        
        public void setData(byte[] data) {
            this.data = data;
        }
        
        public String getFormat() {
            return format;
        }
        
        public void setFormat(String format) {
            this.format = format;
        }
        
        public int getRow() {
            return row;
        }
        
        public void setRow(int row) {
            this.row = row;
        }
        
        public int getColumn() {
            return column;
        }
        
        public void setColumn(int column) {
            this.column = column;
        }
        
        public int getWidth() {
            return width;
        }
        
        public void setWidth(int width) {
            this.width = width;
        }
        
        public int getHeight() {
            return height;
        }
        
        public void setHeight(int height) {
            this.height = height;
        }
        
        @Override
        public String toString() {
            return "ImageInfo{" +
                    "format='" + format + '\'' +
                    ", row=" + row +
                    ", column=" + column +
                    ", width=" + width +
                    ", height=" + height +
                    ", base64Length=" + (base64 != null ? base64.length() : 0) +
                    '}';
        }
    }
    
    /**
     * 从Excel文件中提取指定sheet的所有图片
     * 
     * @param filePath Excel文件路径(.xlsx或.xlsm格式)
     * @param sheetIndex sheet索引(从0开始)
     * @return 图片信息列表
     */
    public static List<ImageInfo> extractImagesFromSheet(String filePath, int sheetIndex) {
        FileInputStream fis = null;
        Workbook workbook = null;
        
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                log.error("文件不存在: {}", filePath);
                return Collections.emptyList();
            }
            
            fis = new FileInputStream(file);
            workbook = WorkbookFactory.create(fis);
            
            if (sheetIndex >= workbook.getNumberOfSheets()) {
                log.error("sheet索引超出范围: {}, 总sheet数: {}", sheetIndex, workbook.getNumberOfSheets());
                return Collections.emptyList();
            }
            
            Sheet sheet = workbook.getSheetAt(sheetIndex);
            
            if (workbook instanceof XSSFWorkbook) {
                return extractImagesFromXSSFSheet((XSSFSheet) sheet);
            } else if (workbook instanceof HSSFWorkbook) {
                return extractImagesFromHSSFSheet((HSSFSheet) sheet, (HSSFWorkbook) workbook);
            } else {
                log.error("不支持的工作簿类型: {}", workbook.getClass().getName());
                return Collections.emptyList();
            }
            
        } catch (Exception e) {
            log.error("提取Excel图片失败", e);
            return Collections.emptyList();
        } finally {
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    log.error("关闭工作簿失败", e);
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    log.error("关闭文件流失败", e);
                }
            }
        }
    }
    
    /**
     * 从Excel文件中提取指定sheet名称的所有图片
     * 
     * @param filePath Excel文件路径
     * @param sheetName sheet名称
     * @return 图片信息列表
     */
    public static List<ImageInfo> extractImagesFromSheet(String filePath, String sheetName) {
        FileInputStream fis = null;
        Workbook workbook = null;
        
        try {
            fis = new FileInputStream(new File(filePath));
            workbook = WorkbookFactory.create(fis);
            
            Sheet sheet = workbook.getSheet(sheetName);
            if (sheet == null) {
                log.error("找不到名为 {} 的sheet", sheetName);
                return Collections.emptyList();
            }
            
            if (workbook instanceof XSSFWorkbook) {
                return extractImagesFromXSSFSheet((XSSFSheet) sheet);
            } else if (workbook instanceof HSSFWorkbook) {
                return extractImagesFromHSSFSheet((HSSFSheet) sheet, (HSSFWorkbook) workbook);
            } else {
                return Collections.emptyList();
            }
            
        } catch (Exception e) {
            log.error("提取Excel图片失败", e);
            return Collections.emptyList();
        } finally {
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    log.error("关闭工作簿失败", e);
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    log.error("关闭文件流失败", e);
                }
            }
        }
    }
    
    /**
     * 从XSSF格式的sheet中提取图片(.xlsx/.xlsm)
     */
    private static List<ImageInfo> extractImagesFromXSSFSheet(XSSFSheet sheet) {
        List<ImageInfo> imageList = new ArrayList<>();
        
        for (POIXMLDocumentPart dr : sheet.getRelations()) {
            if (dr instanceof XSSFDrawing) {
                XSSFDrawing drawing = (XSSFDrawing) dr;
                for (XSSFShape shape : drawing.getShapes()) {
                    if (shape instanceof XSSFPicture) {
                        XSSFPicture pic = (XSSFPicture) shape;
                        XSSFClientAnchor anchor = pic.getPreferredSize();
                        CTMarker ctMarker = anchor.getFrom();
                        
                        ImageInfo imageInfo = new ImageInfo();
                        imageInfo.setRow(ctMarker.getRow());
                        imageInfo.setColumn(ctMarker.getCol());
                        
                        PictureData pictureData = pic.getPictureData();
                        byte[] data = pictureData.getData();
                        imageInfo.setData(data);
                        imageInfo.setBase64(Base64.getEncoder().encodeToString(data));
                        imageInfo.setFormat(getImageFormat(pictureData));
                        
                        // 获取图片尺寸
                        try {
                            java.awt.Dimension dimension = pic.getImageDimension();
                            imageInfo.setWidth(dimension.width);
                            imageInfo.setHeight(dimension.height);
                        } catch (Exception e) {
                            log.warn("无法获取图片尺寸", e);
                        }
                        
                        imageList.add(imageInfo);
                        log.info("提取到图片: 位置[{},{}], 格式: {}, 大小: {}x{}", 
                                imageInfo.getRow(), imageInfo.getColumn(), 
                                imageInfo.getFormat(), imageInfo.getWidth(), imageInfo.getHeight());
                    }
                }
            }
        }
        
        return imageList;
    }
    
    /**
     * 从HSSF格式的sheet中提取图片(.xls)
     */
    private static List<ImageInfo> extractImagesFromHSSFSheet(HSSFSheet sheet, HSSFWorkbook workbook) {
        List<ImageInfo> imageList = new ArrayList<>();
        List<HSSFPictureData> pictures = workbook.getAllPictures();
        
        if (pictures != null && !pictures.isEmpty() && sheet.getDrawingPatriarch() != null) {
            for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) {
                if (shape instanceof HSSFPicture) {
                    HSSFPicture pic = (HSSFPicture) shape;
                    HSSFClientAnchor anchor = (HSSFClientAnchor) pic.getAnchor();
                    
                    ImageInfo imageInfo = new ImageInfo();
                    imageInfo.setRow(anchor.getRow1());
                    imageInfo.setColumn(anchor.getCol1());
                    
                    HSSFPictureData pictureData = pic.getPictureData();
                    byte[] data = pictureData.getData();
                    imageInfo.setData(data);
                    imageInfo.setBase64(Base64.getEncoder().encodeToString(data));
                    imageInfo.setFormat(getImageFormat(pictureData));
                    
                    imageList.add(imageInfo);
                    log.info("提取到图片: 位置[{},{}], 格式: {}", 
                            imageInfo.getRow(), imageInfo.getColumn(), imageInfo.getFormat());
                }
            }
        }
        
        return imageList;
    }
    
    /**
     * 获取图片格式
     */
    private static String getImageFormat(PictureData pictureData) {
        String mimeType = pictureData.getMimeType();
        if (mimeType != null) {
            if (mimeType.contains("png")) {
                return "png";
            } else if (mimeType.contains("jpeg") || mimeType.contains("jpg")) {
                return "jpg";
            } else if (mimeType.contains("gif")) {
                return "gif";
            } else if (mimeType.contains("bmp")) {
                return "bmp";
            }
        }
        return "unknown";
    }
    
    /**
     * 提取指定位置的图片
     * 
     * @param filePath Excel文件路径
     * @param sheetIndex sheet索引
     * @param row 行号(从0开始)
     * @param column 列号(从0开始)
     * @return 图片信息,如果找不到返回null
     */
    public static ImageInfo extractImageAtPosition(String filePath, int sheetIndex, int row, int column) {
        List<ImageInfo> images = extractImagesFromSheet(filePath, sheetIndex);
        
        for (ImageInfo image : images) {
            if (image.getRow() == row && image.getColumn() == column) {
                return image;
            }
        }
        
        log.warn("在位置[{},{}]未找到图片", row, column);
        return null;
    }
    
    /**
     * 获取所有图片的Base64编码列表
     * 
     * @param filePath Excel文件路径
     * @param sheetIndex sheet索引
     * @return Base64编码列表
     */
    public static List<String> extractImagesAsBase64List(String filePath, int sheetIndex) {
        List<ImageInfo> images = extractImagesFromSheet(filePath, sheetIndex);
        return images.stream()
                .map(ImageInfo::getBase64)
                .collect(Collectors.toList());
    }
    
    /**
     * 打印所有图片的位置信息
     * 
     * @param filePath Excel文件路径
     * @param sheetIndex sheet索引
     */
    public static void printImagePositions(String filePath, int sheetIndex) {
        List<ImageInfo> images = extractImagesFromSheet(filePath, sheetIndex);
        
        System.out.println("\n========== Excel图片位置信息 ==========");
        System.out.println("文件: " + filePath);
        System.out.println("Sheet索引: " + sheetIndex);
        System.out.println("图片数量: " + images.size());
        System.out.println("=======================================\n");
        
        for (int i = 0; i < images.size(); i++) {
            ImageInfo image = images.get(i);
            System.out.println("图片 #" + (i + 1) + ":");
            System.out.println("  位置: 行" + (image.getRow() + 1) + ", 列" + (char)('A' + image.getColumn()));
            System.out.println("  格式: " + image.getFormat());
            System.out.println("  尺寸: " + image.getWidth() + " x " + image.getHeight());
            System.out.println("  数据大小: " + image.getData().length + " bytes");
            System.out.println("  Base64长度: " + image.getBase64().length());
            System.out.println("  Base64预览: " + 
                    (image.getBase64().length() > 50 ? 
                            image.getBase64().substring(0, 50) + "..." : image.getBase64()));
            System.out.println();
        }
    }
}
